--- testSocket
-- @module asyncSocket
-- @author Moore
-- @license MIT
-- @copyright nanmi.cn
-- @release 2019.01.27



require "socket"
--加载JSON功能测试模块
require "testJson"
require "pins"
require "misc"

--加载参数存储功能测试模块
require"config"
require"nvm"


module(..., package.seeall)


-- 此处的IP和端口请填上你自己的socket服务器和端口  测试环境："47.110.59.241","54321" 生产环境:"116.62.123.69","12321"
--local ip, port = "47.110.59.241","54321"
local ip, port = "iot-toilet.mi-me.com","12321"
--local imei = "868440034285006"

nvm.init("config.lua")

--GPIO1配置为输出，默认输出低电平，可通过setGpio1Fnc(0或者1)设置输出电平
--setLED 为LED setBeep 为蜂鸣器 dc_motor为直流电机
local setLED   = pins.setup(pio.P1_1,0)
local setBeep  = pins.setup(pio.P0_6,0)
local dc_motor = pins.setup(pio.P0_7,0)
local ADC_ID = 0
local rising_edge = 0
local trailing_edge = 0
local motortimerid = 0

-- 异步接口演示代码
local asyncClient
local regstate = false

sys.taskInit(function()
    local recv_cnt, send_cnt = 0, 0

    while true do
        while not socket.isReady() do sys.wait(1000) end
        asyncClient = socket.tcp()
        while not asyncClient:connect(ip, port) do sys.wait(5000) end
        while asyncClient:asyncSelect(4*60, jsonhrt) do end  --心跳保持4分钟一个，移动据说是5分钟NAT超时
        asyncClient:close()  --销毁一个socket
    end
end)

--- ADC读取测试
-- @return 无
-- @usage battread()
local function battread()
    -- 打开adc
    adc.open(ADC_ID)
    -- 读取adc
    -- adcval为number类型，表示adc的原始值，无效值为0xFFFF
    -- voltval为number类型，表示转换后的电压值，单位为毫伏，无效值为0xFFFF；adc.read接口返回的voltval放大了3倍，所以需要除以3还原成原始电压
    local adcval,voltval = adc.read(ADC_ID)
	local realvoltval = ((voltval-(voltval%3))/3)*11 -- 这里的单位是毫伏
    log.info("testAdc.read",adcval,realvoltval,voltval)

    --如果voltval有效
    if voltval and voltval~=0xFFFF then
        --adc.read接口返回的voltval放大了3倍，所以此处除以3
        if realvoltval < 6200 then
            asyncClient:asyncSend(jsonadcalm)
		end
    end

    if tonumber((rtos.get_version()):match("Luat_V(%d+)_"))>=27 then
        adc.close(ADC_ID)
		log.info("tadc.close")
    end
end

--- hall传感器的中断管脚绑定
function gpio29IntFnc(msg)
    if msg==cpu.INT_GPIO_POSEDGE
    then
        rising_edge = rising_edge + 1 --上升沿中断
    else
	    trailing_edge = trailing_edge + 1 --下降沿中断
    end

	if motortimerid == 0 and trailing_edge >= 5 --有人手动抽纸
	then
        setBeep(1)
		sys.timerStart(setBeep,3000,0)
		trailing_edge = 0
	end

	if motortimerid ~= 0 and trailing_edge >= 12 --正常出纸
	then
        dc_motor(0)
		sys.timerStop(motortimerid)
		motortimerid = 0
		rising_edge   = 0
		trailing_edge = 0
	end

    --[[
	local turns_Num = nvm.get("turnsPara")
	log.info("turnsPara:",turns_Num)

	if motortimerid ~= 0
	then
	    if turns_Num <= 10
		then
		    if trailing_edge > 20
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		elseif turns_Num <= 20 and turns_Num > 10
		then
		    if trailing_edge > 17
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		elseif turns_Num <= 30 and turns_Num > 20
		then
		    if trailing_edge > 14
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		elseif turns_Num <= 40 and turns_Num > 30
		then
		    if trailing_edge > 11
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		elseif turns_Num <= 50 and turns_Num > 40
		then
		    if trailing_edge > 8
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		else
		    if trailing_edge > 5
			then
                dc_motor(0)
                sys.timerStop(motortimerid)
                motortimerid = 0
				rising_edge   = 0
				trailing_edge = 0
			end
		end
	end]]--
end

--- 直流电机的断电函数
function shutdownmotor(msg)
    dc_motor(0)
    if motortimerid ~= 0
	then
	    motortimerid = 0
	end
	--log.info("scroll alarm!")
	asyncClient:asyncSend(jsontearalm) --任何塑料套断裂、电机转不动的现象都报该告警
end

--GPIO29配置为中断，可通过getGpio29Fnc()获取输入电平，产生中断时，自动执行gpio4IntFnc函数
getGpio29Fnc = pins.setup(pio.P0_29,gpio29IntFnc)


-- 用于异步发送注册消息
local reg_timerid = sys.timerLoopStart(function()
    if socket.isReady() then
        asyncClient:asyncSend(jsonreg)
    end
end, 10000)

-- 用于监视电池电量消息，10分钟一次，万一小于6000mV就报告警
local adc_timerid = sys.timerLoopStart(battread, 60*60*1000)

-- 测试代码，异步回调接收数据
sys.subscribe("SOCKET_RECV", function(id)
    if asyncClient.id == id then
        local data = asyncClient:asyncRecv()
        log.info("这是服务器下发数据……:", #data, type(data), data)
		local tjsondata,result,errinfo = json.decode(data)
        if result and type(tjsondata)=="table" then
		    if tjsondata["PdtName"] == "Toilet" and tjsondata["ConNum"] == misc.getImei()
			then
			    if tjsondata["CmdType"] == "1" and tjsondata["StatFlag"] == "FIN"
				then
				    setLED(1)
					setBeep(1)
				    sys.timerStop(reg_timerid)
					sys.timerStart(setLED,2000,0)
					sys.timerStart(setBeep,2000,0)
			    elseif tjsondata["CmdType"] == "2" and tjsondata["StatFlag"] == "FIN"
				then
                    log.info("heart beat ok!")
				elseif tjsondata["CmdType"] == "3" and tjsondata["StatFlag"] == "ACK"
				then
				    local SnNum = tjsondata["DevNum"] --这里是命令的序列号
					log.info("Scroll SnNum:",SnNum)

					local turnsNum = nvm.get("turnsPara")
					turnsNum = turnsNum + 1
					motortimerid = sys.timerStart(shutdownmotor, 15*1000)
					dc_motor(1)
					nvm.set("turnsPara",turnsNum)
					--log.info("Scroll ok! turnsPara",turnsNum)

					local scrolldata,scrollrlt,errno = json.decode(jsonscroll)
					log.info("scrolldata[DevNum]:",scrolldata["DevNum"])
					scrolldata["DevNum"] = SnNum
					local json_scroll = json.encode(scrolldata)
					asyncClient:asyncSend(json_scroll)

					if turnsNum > 65
					then
					    log.info("send scroll alarm.turnsNum:",turnsNum)
					    asyncClient:asyncSend(jsonrollalm)
					end
			    elseif tjsondata["CmdType"] == "5" and tjsondata["StatFlag"] == "CLR"
			    then
				    nvm.set("turnsPara",0)
                    log.info("sleeve scroll alarm cleared!")
				elseif tjsondata["CmdType"] == "6" and tjsondata["StatFlag"] == "CLR"
				then
				    nvm.set("turnsPara",0)
                    log.info("sleeve tear alarm cleared!")
				else
					log.info("[Error Cmd]:",tjsondata)
				end
			else
			    log.info("[Error Pdt]:",tjsondata)
			end
        else
            log.info("testJson.decode error",errinfo)
        end
    end
end)

--[[
sys.timerLoopStart(function()
    log.info("打印占用的内存:", _G.collectgarbage("count"))-- 打印占用的RAM
    log.info("打印可用的空间", rtos.get_fs_free_size())-- 打印剩余FALSH，单位Byte
end, 5000)]]--
